/*
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.
* gazelle is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*     http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <stdint.h>
#include <sys/socket.h>

#include <lwipgz_flow.h>
#include "lstack_protocol_stack.h"
#include "lstack_log.h"
#include "lstack_rule.h"

static struct vdev_rule_reg_ops *g_vdev_rule_ops;

int vdev_rule_register(struct vdev_rule_reg_ops *ops)
{
    g_vdev_rule_ops = ops;
    return 0;
}

int vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple)
{
    if (qtuple == NULL) {
        return -1;
    }

    int ret = 0;
    uint16_t queue_id = get_stack_queue_id();

    switch (type) {
        case REG_RING_TCP_LISTEN:
        case REG_RING_UDP_BIND:
            ret = g_vdev_rule_ops->reg_listen_port(qtuple, queue_id, type);
            break;
        case REG_RING_TCP_LISTEN_CLOSE:
        case REG_RING_UDP_BIND_CLOSE:
            ret = g_vdev_rule_ops->unreg_listen_port(qtuple, queue_id, type);
            break;
        case REG_RING_TCP_CONNECT:
            ret = g_vdev_rule_ops->reg_conn(qtuple, queue_id, type);
            break;
        case REG_RING_TCP_CONNECT_CLOSE:
            ret = g_vdev_rule_ops->unreg_conn(qtuple, queue_id, type);
            break;
        case REG_RING_FIND_CONN:
            if (g_vdev_rule_ops->find_conn != NULL) {
                ret = g_vdev_rule_ops->find_conn(qtuple, queue_id, type);
            } else {
                ret = queue_id;
            }
            break;
        case REG_RING_FIND_LISTEN_PORT:
            if (g_vdev_rule_ops->find_listen_port != NULL) {
                ret = g_vdev_rule_ops->find_listen_port(qtuple, queue_id, type);
            } else {
                ret = queue_id;
            }
            break;
        default:
            LSTACK_LOG(ERR, LSTACK, "unkonw rte ring type\n");
            return -1;
    }

    return ret;
}
